import { Injectable, UseFilters } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { InjectRepository } from '@nestjs/typeorm';
import { isNil } from 'ramda';
import { HttpExceptionFilter } from 'src/common/http-exception.filter';
import { errorState, getPagination, successState, throwHttp } from 'src/utlis';
import { isTrue } from 'src/utlis/tools';
import { Between, Connection, Like, Repository } from 'typeorm';
import {
  CreateRoleDto,
  GetRolePageDto,
  RoleAuthConfigDto,
  UpdateRoleDto,
} from './dto/role.dto';
import { RoleEntity } from './entities/role.entity';
import { TokenDto } from 'src/common/auth/constants';

@Injectable()
export class RoleService {
  constructor(
    @InjectRepository(RoleEntity)
    private readonly roleEntityRepository: Repository<RoleEntity>,
    private readonly jwtService: JwtService,
    private readonly connection: Connection,
  ) { }
  /** 角色列表 */
  async getRolePage(params: GetRolePageDto) {
    try {
      const {
        createTimeStart,
        createTimeEnd,
        updateTimeEnd,
        updateTimeStart,
        rolename,
        isEnable,
      } = params;
      const { pageSize, pageNum } = getPagination({
        pageSize: params.pageSize,
        pageNum: params.pageNum,
      });
      const where: GetRolePageDto = {
        rolename: Like(`%${rolename || ''}%`),
        isEnable,
      };
      // 时间筛选
      if (!isNil(createTimeStart) && !isNil(createTimeEnd)) {
        where.createDate = Between(createTimeStart, createTimeEnd);
      }
      // 更新时间筛选
      if (!isNil(updateTimeStart) && !isNil(updateTimeEnd)) {
        where.updateDate = Between(updateTimeStart, updateTimeEnd);
      }
      const [data, total] = await this.roleEntityRepository.findAndCount({
        where,
        cache: true,
        skip: pageNum * pageSize,
        take: pageSize,
        order: { createDate: 'DESC' },
      });
      return {
        data: data.map((item) => {
          if (isTrue(item.menu)) {
            item.menu = JSON.parse(item.menu ?? '[]');
          }
          return item;
        }),
        total,
        pageSize,
        pageNum: pageNum * pageSize + 1,
      };
    } catch (error) {
      throwHttp(error.message);
    }
  }
  /** 获取角色详情 */
  @UseFilters(new HttpExceptionFilter())
  async getRoleInfo(where) {
    try {
      return await this.roleEntityRepository.findOne({
        where,
      });
    } catch (error) {
      throwHttp(error.message);
    }
  }
  /** 创建角色 */
  @UseFilters(new HttpExceptionFilter())
  async createValidateHeaders(body: CreateRoleDto, headers) {
    try {
      const token = headers.authorization.split(' ');
      if (!isTrue(token)) {
        throwHttp('获取token失败');
      }
      const user = this.jwtService.decode(token[1]) as TokenDto;
      await this.createRole(body, user.userId)
    } catch (error) {
      throwHttp(error.message);
    }
  }
  async createRole(body, userId) {
    try {
      const { rolename, description, menu } = body;
      const data = await this.getRoleInfo({ rolename });
      if (isTrue(data)) {
        throwHttp('已有相同名称的角色');
        return;
      }
      const role = new RoleEntity();
      role.rolename = rolename;
      role.description = description;
      role.menu = menu;
      role.createById = userId;
      const result = await this.roleEntityRepository.manager.save(role);
      return isTrue(result) ? '角色创建成功' : '角色创建失败';
    } catch (error) {
      throwHttp(error.message);
    }
  }
  /** 更新角色信息 */
  @UseFilters(new HttpExceptionFilter())
  async updateRole(body: UpdateRoleDto) {
    // 获取连贯并创立新的queryRunner
    const queryRunner = this.connection.createQueryRunner();
    // 应用咱们的新queryRunner建设真正的数据库连
    await queryRunner.connect();
    // 开始事务
    await queryRunner.startTransaction();
    try {
      const { id, rolename, description, isEnable } = body;
      const data = await this.getRoleInfo({ id });
      if (!isTrue(data)) {
        await queryRunner.rollbackTransaction();
        return errorState('角色不存在');
      }
      const role = new RoleEntity();
      role.id = id;
      role.rolename = rolename;
      role.description = description;
      role.createById = data.createById;
      role.isEnable = isEnable;
      const result = await queryRunner.manager
        .getRepository(RoleEntity)
        .save(role);
      if (!isTrue(result)) {
        await queryRunner.rollbackTransaction();
        return errorState('更新失败');
      }
      await queryRunner.commitTransaction();
      return successState('更新成功');
    } catch (error) {
      // 出错回滚
      console.log('创立失败，勾销事务');
      await queryRunner.rollbackTransaction();
      return errorState(error.message);
    } finally {
      // 开释
      await queryRunner.release();
    }
  }
  /** 角色权限配置 */
  @UseFilters(new HttpExceptionFilter())
  async roleAuthConfig(params: RoleAuthConfigDto) {
    try {
      const { id, menu } = params;
      const roleInfo = await this.getRoleInfo({ id });
      if (!isTrue(roleInfo)) {
        throwHttp('角色不存在');
      }
      const { affected } = await this.roleEntityRepository
        .createQueryBuilder()
        .update(RoleEntity)
        .set({ menu })
        .where('id = :id', { id })
        .execute();
      if (affected) {
        return '更新成功';
      }
      throwHttp('更新分类失败');
    } catch (error) {
      throwHttp(error.message);
    }
  }
  async addRoleIfNotExists(userId: number) {
    const data = await this.roleEntityRepository.findOne({
      where: {
        rolename: 'admin'
      }
    })
    if (!data) {
      await this.createRole({
        rolename: 'admin',
        isEnable: '1',
        description: '系统创建',
        menu: '[{"name":"Backstage","path":"/backstage","component":{"name":"layout","components":{"r-content":{"__name":"content","__hmrId":"27277cad","__file":"E:/个人文件/nuxt-ssr/vue-admin-antd-formwork/src/layout/content.vue"}},"__hmrId":"2f895794"},"meta":{"title":"用户管理"},"children":[{"name":"Role","path":"/backstage/role","meta":{"title":"角色管理"},"key":"Role","checked":true},{"name":"AdminUser","path":"/backstage/adminUser","meta":{"title":"后台用户管理"},"key":"AdminUser","checked":true}],"key":"Backstage","checked":true}]',
      }, userId)
      const data = await this.roleEntityRepository.findOne({
        where: {
          rolename: 'admin'
        }
      })
      return data
    }
    return data
  }
}
